﻿using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Text;
using WW.Cad.IO;
using WW.Cad.Model;
using WW.Cad.Model.Entities;

namespace ZhZyz.Cad
{
    public class CadHelper
    {
        private readonly string _filepath;
        private readonly DxfModel _model;
        private static Dictionary<string, string> _cassdic;
        public CadHelper(string cadFile)
        {
            _filepath = cadFile;
            _model = OpenCadFile(_filepath);
            //_cad = new CadServices();
        }
        /// <summary>
        /// 根据CASS获取线
        /// </summary>
        /// <param name="casscode"></param>
        /// <param name="formatType">0 WKT，1 GeoJson</param>
        /// <returns></returns>
        public string[] GetPlByCass(string casscode, int formatType)
        {
            var entities = CadServices.GetPlEntites(_model);
            List<string> pljsons = new List<string>();
            var dxfs = new List<DxfEntity>();

            foreach (var ent in entities)
            {
                var datas = ent.ExtendedDataCollection;

                if (datas.TryGetValue(_model, "SOUTH", out var extData))
                {
                    var casscode1 = extData.Values[0].ToString();
                    if (casscode1 == casscode)
                    {
                        dxfs.Add(ent);
                        var json = CadServices.ConvertEntToJson(ent, formatType==0);
                        JObject jo = JObject.Parse(json);
                        jo["properties"]["Cass"] = casscode;
                        jo["properties"]["CassDesc"] = GetCassDesc(casscode);
                        jo["properties"]["File"] = Path.GetFileName(_filepath);
                       // jo["properties"]["Cass"] = casscode;
                        json = jo.ToString(Newtonsoft.Json.Formatting.None);
                        pljsons.Add(json);
                        
                    }
                }
            }

            return pljsons.ToArray();
        }



        #region 静态方法

    public  delegate void ProcessEventHandle(string msg);
        public static event ProcessEventHandle ProcessEvent;

        /// <summary>
        /// 获取CASS编码说明
        /// </summary>
        /// <param name="casscode"></param>
        /// <returns></returns>
        public static string GetCassDesc(string casscode)
        {
            if (_cassdic == null)
            {
                _cassdic = new Dictionary<string, string>();
                var allLn = File.ReadAllLines(Path.GetDirectoryName( Assembly.GetEntryAssembly().Location) + "\\index.ini", Encoding.Default);
                foreach (var s in allLn)
                {
                    var sv = s.Split(',');
                    if (sv.Length >= 4)
                        _cassdic[sv[0]] = sv[3];
                }
            }
            _cassdic.TryGetValue(casscode, out var result);
            return result;
        }
        public void SaveDoc()
        {
            SaveCadFile(_model, _filepath);
        }



        /// <summary>
        /// 根据 图层-编码字典，对所有文件进行读取
        /// </summary>
        /// <param name="layandCass">图层+点线面为键，编码列表</param>
        /// <param name="files">文件列表</param>
        /// <returns></returns>
        public static void GetAllByCass(Dictionary<string, List<string>> layerAndCass,string[] files)
        {
            var outpath = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
            //清空原的gkt文件
            string[] fs = Directory.GetFiles(outpath, "*.gkt");
            foreach (var item in fs)
            {
                File.Delete(item);
            }

            ProcessEvent($"*****开始读取{DateTime.Now.ToShortTimeString()}*****\r\n");
            DateTime beginTm = DateTime.Now;
            foreach (var file in files)
            {
                ProcessEvent($"获取文件{Path.GetFileName(file)}中的编码数据。。");
                var model = OpenCadFile(file);
                var entities = model.Entities;//  CadServices.GetPlEntites(model);
                Dictionary<string, List<string>> result = new Dictionary<string, List<string>>();
                foreach (var ent in entities)
                {
                 
                    var datas = ent.ExtendedDataCollection;
                    if (datas.TryGetValue(model, "SOUTH", out var extData))
                    {
                        var casscode = extData.Values[0].ToString();

                        if (HasCode(layerAndCass, casscode, out var layerout))
                        {
                            var json = CadServices.ConvertEntToJson(ent, true, layerout.EndsWith("pg"));
                            JObject jo = JObject.Parse(json);
                            jo["properties"]["Cass"] = casscode;
                            jo["properties"]["CassDesc"] = GetCassDesc(casscode);
                            jo["properties"]["File"] = Path.GetFileName(file);
                            // jo["properties"]["Cass"] = casscode;
                            json = jo.ToString(Newtonsoft.Json.Formatting.None);

                            if (result.ContainsKey(layerout))
                            {
                                result[layerout].Add(json);
                            }
                            else
                            {
                                result.Add(layerout, new List<string>() { json });
                            }

                        }
                    }
                }
                model.Dispose();
                model = null;
                //结果写出到文件

                ProcessEvent($"保存中...\r\n");
                WriteCode(result, outpath);
                result.Clear();
            }

            ProcessEvent($"*****读取完成{DateTime.Now.ToShortTimeString()} 用时：{(DateTime.Now-beginTm).TotalMinutes:f2}分*****\r\n");
        }

        public static void GetAllCass(string text)
        {
            var outpath = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
            
            Dictionary<string, string> result = new Dictionary<string, string>();
            ProcessEvent($"*****开始读取{DateTime.Now.ToShortTimeString()}*****\r\n");
            DateTime beginTm = DateTime.Now;
            foreach (var file in Directory.GetFiles(text,"*.dwg"))
            {
                ProcessEvent($"获取文件{Path.GetFileName(file)}中的编码数据。。\r\n");
                var model = OpenCadFile(file);
                var entities = model.Entities;//  CadServices.GetPlEntites(model);
          
                foreach (var ent in entities)
                {

                    var datas = ent.ExtendedDataCollection;
                    if (datas.TryGetValue(model, "SOUTH", out var extData))
                    {
                        var casscode = extData.Values[0].ToString();
                        if (!result.ContainsKey(casscode)) result.Add(casscode, GetCassDesc(casscode));

                    }
                }
                model.Dispose();
                model = null;
  
            }
            //结果写出到文件

            ProcessEvent($"保存中...\r\n");
            StreamWriter sw = new StreamWriter(outpath + "\\CassAll.txt");
            foreach (var item in result)
            {
                sw.WriteLine($"{item.Key},{item.Value}");
            }
            sw.Flush();
            sw.Close();
            
            result.Clear();
            ProcessEvent($"*****读取完成{DateTime.Now.ToShortTimeString()} 用时：{(DateTime.Now - beginTm).TotalMinutes:f2}分*****\r\n");
        }

        private static void WriteCode(Dictionary<string, List<string>> result, string outdir)
        {

            foreach (var item in result)
            {
                var vpath = outdir+ "\\" + item.Key + ".gkt";
                File.AppendAllLines(vpath, item.Value.ToArray());
            }
        }
        public static void GetAllByCass(string laycassPath, string filespath)
                {
            string[] svs = System.IO.File.ReadAllLines(laycassPath);
            Dictionary<string, List<string>> layerAndCass = new Dictionary<string, List<string>>();
            string[] files = Directory.GetFiles(filespath, "*.dwg");
            var curlay = "";
            foreach (var sv in svs)
            {
                string[] sqs = sv.Split(',');
                if (sqs.Length ==1)
                {
                    curlay =sv;

                }
                else if (sqs.Length >=2)
                {
                    if (!layerAndCass.ContainsKey(curlay)) layerAndCass.Add(curlay, new List<string>());
                    layerAndCass[curlay].Add(sqs[0]);
                }
            }

            GetAllByCass(layerAndCass, files);

        }

        private static bool HasCode(Dictionary<string, List<string>> layerAndCass, string code, out string layer)
        {
            layer = "";
            foreach (var item in layerAndCass)
            {
                if (item.Value.Contains(code))
                {
                    layer = item.Key;
                    return true;
        
                }
            }
            return false;
        }



        /// <summary>
        ///     打开CAD文件
        /// </summary>
        /// <param name="cadFile">CAD文件完整路径</param>
        /// <returns>dxfmodel</returns>
        private static DxfModel OpenCadFile(string cadFile)
        {
            var ext = Path.GetExtension(cadFile);
            DxfModel model = null;

            switch (ext.ToUpper())
            {
                case ".DWG":
                    Stream stream = new FileStream(cadFile,FileMode.Open,FileAccess.Read);
                    model = DwgReader.Read(stream);
                    stream.Close();
                    break;
                case ".DXF":
                    Stream stream1 = new FileStream(cadFile, FileMode.Open, FileAccess.Read);
                    model = DxfReader.Read(stream1);
                    stream1.Close();
                    break;
            }

            return model;
        }

        /// <summary>
        ///     根据文件扩展名 保存CAD文件
        /// </summary>
        /// <param name="model">模型</param>
        /// <param name="filepath">文件路径</param>
        private static void SaveCadFile(DxfModel model, string filepath)
        {
            var ext = Path.GetExtension(filepath);
            model.ResetHandles(); //重设句柄，避免引起异常
            model.Header.DrawingCodePage = DrawingCodePage.Gb2312; //修改代码页，否则保存中文后再打开变成乱码
            switch (ext.ToUpper())
            {
                case ".DWG":
                    if ((int) model.Header.AcadVersion < 14) model.Header.AcadVersion = DxfVersion.Dxf14;
                    DwgWriter.Write(filepath, model);
                    break;
                case ".DXF":
                    DxfWriter.Write(filepath, model);
                    break;
            }
        }
        #endregion
    }
}